#include <QCoreApplication>
#include <QTimer>
#include <QThread>
#include <QDateTime>
#include <QNetworkAccessManager>
#include <QNetworkRequest>
#include <QNetworkReply>
#include <QJsonDocument>
#include <QJsonObject>
#include <QJsonArray>
#include <QProcess>
#include <QDebug>

#include "setting/JSON_settings.h"
#include "setting/version.h"
#include "coordinator/coordinator.h"
#include "cloud_http.h"

extern bool FilterLogMessage(QDateTime from, QDateTime to);

#define Network_Transfer_Timeout	(10 * 1000)				// 10 seconds
#define HeartBreak_Period_Normal	(5 * 60 * 1000)			// 5 minutes
#define HeartBreak_Period_Abnormal	(15 * 1000)				// 15 seconds
#define Upgrade_Period				(30 * 60 * 1000)		// half hour

HttpCloud_Worker::HttpCloud_Worker(Coordinator *coordinator, QObject *parent)
	: QObject(parent)
{
    QSettings settings(JSONSettings::GetSettingFilePath(), JSONSettings::GetFormat(), QCoreApplication::instance());

    m_coordinator = coordinator;
	m_heartbreak_timer = nullptr;
	m_upgrade_timer = nullptr;
    m_server_address = settings.value(JSON_HTTP_SERVER_IP).toString();
	m_auth_code = settings.value(JSON_HTTP_AUTHENTICATE_CODE).toString();
	m_online = false;
    s_aes_private_key = settings.value(JSON_HTTP_PRIVATE_KEY).toString().toUtf8();
    m_heartbreak_period = settings.value(JSON_HTTP_HEARTBREAK_PERIOD).toInt();
    m_transfer_timeout = settings.value(JSON_HTTP_TRANSFER_TIMEOUT).toInt();
    if (m_heartbreak_period == 0)
    	m_heartbreak_period = HeartBreak_Period_Normal;
    if (m_transfer_timeout == 0)
    	m_transfer_timeout = Network_Transfer_Timeout;
}

HttpCloud_Worker::~HttpCloud_Worker()
{
	stop_work();
}

void HttpCloud_Worker::start_work()
{
	m_heartbreak_timer = new QTimer(this);
    connect(m_heartbreak_timer, &QTimer::timeout, this, &HttpCloud_Worker::heartbreak);
    m_heartbreak_timer->start(1000);
    m_upgrade_timer = new QTimer(this);
    connect(m_upgrade_timer, &QTimer::timeout, this, &HttpCloud_Worker::upgrade_check);
    m_upgrade_timer->start(Upgrade_Period);
}

void HttpCloud_Worker::stop_work()
{
	if (m_heartbreak_timer)
		delete m_heartbreak_timer;
	m_heartbreak_timer = nullptr;
}

#define TRANS_KEY_REPORT_TYPE		"reportType"
#define TRANS_KEY_DEVICE_NO			"deviceNo"
#define TRANS_KEY_TRADE_NO			"tradeNo"
#define TRANS_KEY_TRADE_DATE		"tradeDate"
#define TRANS_KEY_TRADE_TIME		"tradeTime"
#define TRANS_KEY_TRADE_PIECE		"tradePiece"
#define TRANS_KEY_TRADE_AMOUNT		"tradeAmount"
#define TRANS_KEY_OPERATOR_ID		"operatorID"
#define TRANS_KEY_USER_NAME			"userName"
#define TRANS_KEY_SITE_NAME			"siteName"
#define TRANS_KEY_DEPOSIT_TYPE		"depositeType"
#define TRANS_KEY_TRANS_INFO		"transInfos"
#define TRANS_KEY_TRANS_TYPE		"tradeType"
#define TRANS_KEY_TRANS_PIECE		"piece"
#define TRANS_KEY_TRANS_AMOUNT		"amount"
#define TRANS_KEY_TRANS_SERIAL_INFO	"serialInfo"

#define RESP_KEY_RESULT				"result"
#define RESP_KEY_RESULT_MSG			"resultMsg"

#define TRANS_VAL_REPORT_TYPE		"TDSQ"

bool HttpCloud_Worker::upload_transaction(TransInfo trans_info)
{
	bool success = false;
	QNetworkAccessManager manager;
    QNetworkRequest request;
	QByteArray req_data;

	Coordinator::DeviceStatus dev_status = m_coordinator->get_dev_status();
    req_data = QString("deviceNo=%1&params=").arg(dev_status.terminal_id).toUtf8();

    QJsonObject trans;
    QJsonArray trans_array;
	trans.insert(TRANS_KEY_REPORT_TYPE, TRANS_VAL_REPORT_TYPE);
    trans.insert(TRANS_KEY_DEVICE_NO, dev_status.terminal_id);
	trans.insert(TRANS_KEY_TRADE_NO, QString("%1%2").arg(trans_info.date_time.toString("yyyyMMddhhmmss")).arg(trans_info.id));
    trans.insert(TRANS_KEY_TRADE_DATE, trans_info.date_time.toString("yyyyMMdd"));
	trans.insert(TRANS_KEY_TRADE_TIME, trans_info.date_time.toString("hhmmss"));
    trans.insert(TRANS_KEY_TRADE_PIECE, QString("%1").arg(trans_info.note_info.total_count));
    trans.insert(TRANS_KEY_TRADE_AMOUNT, QString("%1").arg(trans_info.note_info.total_amount / 100.0, 0, 'f', 2));
    trans.insert(TRANS_KEY_OPERATOR_ID, trans_info.user_name);
    trans.insert(TRANS_KEY_USER_NAME, trans_info.user_alias);
    trans.insert(TRANS_KEY_SITE_NAME, trans_info.terminal_name);
	trans.insert(TRANS_KEY_TRANS_TYPE, QString("%1").arg(((trans_info.note_info.trans_type % 2) == TRANS_CLASS_NOTE) ? "01" : "02"));
	trans.insert(TRANS_KEY_DEPOSIT_TYPE, QString("%1").arg(Coordinator::coordinator()->category_description(trans_info.note_info.trans_type / 10 - 1)));

	QJsonObject note_info;
	note_info.insert(TRANS_KEY_TRANS_TYPE, QString("%1").arg(((trans_info.note_info.trans_type % 2) == TRANS_CLASS_NOTE) ? "01" : "02"));
	note_info.insert(TRANS_KEY_TRANS_PIECE, QString("%1").arg(trans_info.note_info.total_count));
    note_info.insert(TRANS_KEY_TRANS_AMOUNT, QString("%1").arg(trans_info.note_info.total_amount / 100.0, 0, 'f', 2));
	QJsonArray note_serials;
	note_info.insert(TRANS_KEY_TRANS_SERIAL_INFO, note_serials);
    
    trans_array.append(note_info);
    trans.insert(TRANS_KEY_TRANS_INFO, trans_array);

    req_data += aes_encrypt(QJsonDocument(trans).toJson());

    request.setUrl(m_server_address);
	request.setHeader(QNetworkRequest::ContentTypeHeader, QVariant("application/x-www-form-urlencoded"));
	request.setHeader(QNetworkRequest::ContentLengthHeader, QVariant(req_data.length()));
	manager.setTransferTimeout(m_transfer_timeout);
	QNetworkReply *reply = manager.post(request, req_data);

	QEventLoop loop;
    connect(reply, SIGNAL(finished()), &loop, SLOT(quit()));
	loop.exec();

	if (reply->error() == QNetworkReply::NoError) {
		QByteArray response = reply->readAll();
        QJsonDocument resp_doc = QJsonDocument::fromJson(response);
        if (resp_doc.isObject()) {
        	QJsonObject resp_obj = resp_doc.object();
            uint32_t result = resp_obj.value(RESP_KEY_RESULT).toInt();
        	QString result_msg = resp_obj.value(RESP_KEY_RESULT_MSG).toString();
            if (result == 0) {
	        	qInfo() << "[HTTP]Transaction upload success!";
				success = true;
				transaction_uploaded(trans_info);
        	}
        	else
	        	qInfo() << "[HTTP]Transaction upload failed!" << result << result_msg;
        }
		m_online = true;
        m_heartbreak_timer->setInterval(m_heartbreak_period);
	}
	else {
		qInfo() << "[HTTP]Failure" << reply->errorString();
		m_online = false;
        m_heartbreak_timer->setInterval(HeartBreak_Period_Abnormal);
	}
	delete reply;

	return success;
}

#define UPGRADE_KEY_REPORT_TYPE		"reportType"
#define UPGRADE_KEY_DEVICE_NO		"deviceNo"
#define UPGRADE_KEY_DEVICE_TYPE		"type"

#define UPGRADE_VAL_REPORT_TYPE		"LVSQ"

#define UPGRADE_VAL_RH530_TYPE		2

#define RESP_KEY_DATA				"data"
#define RESP_KEY_DATA_DEVICE_TYPE	"type"
#define RESP_KEY_DATA_DOWNLOADLINK	"downloadLink"
#define RESP_KEY_DATA_FILEPATH		"filePath"
#define RESP_KEY_DATA_VERSION		"version"

void HttpCloud_Worker::upgrade_check()
{
	QNetworkAccessManager manager;
    QNetworkRequest request;
	QByteArray req_data;

	Coordinator::DeviceStatus dev_status = m_coordinator->get_dev_status();
    req_data = QString("deviceNo=%1&params=").arg(dev_status.terminal_id).toUtf8();

    QJsonObject info;
    info.insert(UPGRADE_KEY_REPORT_TYPE, UPGRADE_VAL_REPORT_TYPE);
    info.insert(UPGRADE_KEY_DEVICE_NO, dev_status.terminal_id);
    info.insert(UPGRADE_KEY_DEVICE_TYPE, (qint64) UPGRADE_VAL_RH530_TYPE);
    req_data += aes_encrypt(QJsonDocument(info).toJson());

	request.setUrl(m_server_address);
	request.setHeader(QNetworkRequest::ContentTypeHeader, QVariant("application/x-www-form-urlencoded"));
	request.setHeader(QNetworkRequest::ContentLengthHeader, QVariant(req_data.length()));
	manager.setTransferTimeout(m_transfer_timeout);
	QNetworkReply *reply = manager.post(request, req_data);

	QEventLoop loop;
    connect(reply, SIGNAL(finished()), &loop, SLOT(quit()));
	loop.exec();

	if (reply->error() == QNetworkReply::NoError) {
		QByteArray response = reply->readAll();
        QJsonDocument resp_doc = QJsonDocument::fromJson(response);
        if (resp_doc.isObject()) {
        	QJsonObject resp_obj = resp_doc.object();
        	uint32_t result = resp_obj.value(RESP_KEY_RESULT).toInt();
        	QString result_msg = resp_obj.value(RESP_KEY_RESULT_MSG).toString();
        	if (result == 0) {
                qInfo() << "[HTTP]Upgrade inquiry success!" << result_msg;

                QJsonObject data_obj = resp_obj.value(RESP_KEY_DATA).toObject();
                if (!data_obj.empty()) {
                    uint32_t mach_type = data_obj.value(RESP_KEY_DATA_DEVICE_TYPE).toInt();
                    QString sw_link = data_obj.value(RESP_KEY_DATA_DOWNLOADLINK).toString();
                    QString sw_name = data_obj.value(RESP_KEY_DATA_FILEPATH).toString();
                    QString sw_version = data_obj.value(RESP_KEY_DATA_VERSION).toString();

                    if (mach_type == UPGRADE_VAL_RH530_TYPE)
                        emit sw_upgrade(sw_link, sw_name, sw_version);
                }
        	}
	        else
	        	qInfo() << "[HTTP]Upgrade inquiry failed!" << result << result_msg;
        }
		m_online = true;
        m_heartbreak_timer->setInterval(m_heartbreak_period);
	}
	else {
		qInfo() << "[HTTP]Failure" << reply->errorString();
		m_online = false;
        m_heartbreak_timer->setInterval(HeartBreak_Period_Abnormal);
	}
	delete reply;
}

#define DEV_KEY_REPORT_TYPE			"reportType"
#define DEV_KEY_SW_VERSION			"swvers"
#define DEV_KEY_DEVICE_NO			"deviceNo"
#define DEV_KEY_DEVICE_STATUS		"deviceStatus"
#define DEV_KEY_STATUS				"status"
#define DEV_KEY_BOX_STATUS			"boxStatus"
#define DEV_KEY_NOTE_AMOUNT			"boxDeposit"
#define DEV_KEY_COIN_AMOUNT			"boxManual"
#define DEV_KEY_NOTE_COUNT			"boxDepositPiece"
#define DEV_KEY_COIN_COUNT			"boxManualPiece"
#define DEV_KEY_SETTING_OBJ			"settings"
#define DEV_KEY_AUTO_STORE			"auto_note_store"
#define DEV_KEY_AUTO_COUNT			"auto_note_count"
#define DEV_KEY_USE_AMOUNT_LIMIT	"use_amount_limit"
#define DEV_KEY_CURR_AMOUNT_LIMIT	"note_current_amount_limit"
#define DEV_KEY_MAX_AMOUNT_LIMIT	"note_max_amount_limit"
#define DEV_KEY_ACCOUNT_FAILED_TRANS	"acount_failed_trans"

#define RESP_KEY_DATA_OBJ			"data"
#define RESP_KEY_REQUEST_TYPE		"type"
#define RESP_KEY_DEV_ID				"id"
#define RESP_KEY_FROM_DATE			"beginTime"
#define RESP_KEY_TO_DATE			"endTime"
#define RESP_KEY_SIZE_LIMIT			"limit"

#define RESP_KEY_SETTING_OBJ		"settings"
#define RESP_KEY_AUTO_STORE			"auto_note_store"
#define RESP_KEY_AUTO_COUNT			"auto_note_count"
#define RESP_KEY_USE_AMOUNT_LIMIT	"use_amount_limit"
#define RESP_KEY_CURR_AMOUNT_LIMIT	"note_current_amount_limit"
#define RESP_KEY_MAX_AMOUNT_LIMIT	"note_max_amount_limit"
#define RESP_KEY_ACCOUNT_FAILED_TRANS	"acount_failed_trans"

#define DEV_VAL_REPORT_TYPE			"MSSQ"

#define RESP_REQUEST_SURVEILLANCE_TYPE	1
#define RESP_REQUEST_LOG_TYPE		2

void HttpCloud_Worker::heartbreak()
{
	QNetworkAccessManager manager;
    QNetworkRequest request;
	QByteArray req_data;

	Coordinator::DeviceStatus dev_status = m_coordinator->get_dev_status();
    req_data = QString("deviceNo=%1&params=").arg(dev_status.terminal_id).toUtf8();

    QJsonObject info;
	info.insert(DEV_KEY_REPORT_TYPE, DEV_VAL_REPORT_TYPE);
    info.insert(DEV_KEY_SW_VERSION, sw_version());
    info.insert(DEV_KEY_DEVICE_NO, dev_status.terminal_id);
    info.insert(DEV_KEY_DEVICE_STATUS, (qint64) dev_status.dev_status);
    info.insert(DEV_KEY_STATUS, (qint64) dev_status.state);
    info.insert(DEV_KEY_BOX_STATUS, (qint64) dev_status.bag_status);
	info.insert(DEV_KEY_NOTE_AMOUNT, dev_status.note_amount / 100.0);
	info.insert(DEV_KEY_COIN_AMOUNT, dev_status.coin_amount / 100.0);
	info.insert(DEV_KEY_NOTE_COUNT, (qint64) dev_status.note_count);
	info.insert(DEV_KEY_COIN_COUNT, (qint64) dev_status.coin_count);
	QJsonObject setting;
	setting.insert(DEV_KEY_AUTO_COUNT, m_coordinator->get_auto_count());
	setting.insert(DEV_KEY_AUTO_STORE, m_coordinator->get_auto_store());
    setting.insert(DEV_KEY_USE_AMOUNT_LIMIT, m_coordinator->get_use_amount_limit());
	setting.insert(DEV_KEY_CURR_AMOUNT_LIMIT, m_coordinator->get_curr_amount_limit() / 100.0);
    setting.insert(DEV_KEY_MAX_AMOUNT_LIMIT, m_coordinator->get_max_amount_limit() / 100.0);
	setting.insert(DEV_KEY_ACCOUNT_FAILED_TRANS, m_coordinator->get_account_failed_trans());
	info.insert(DEV_KEY_SETTING_OBJ, setting);

    req_data += aes_encrypt(QJsonDocument(info).toJson());

    request.setUrl(m_server_address);
	request.setHeader(QNetworkRequest::ContentTypeHeader, QVariant("application/x-www-form-urlencoded"));
	request.setHeader(QNetworkRequest::ContentLengthHeader, QVariant(req_data.length()));
	manager.setTransferTimeout(m_transfer_timeout);
    QNetworkReply *reply = manager.post(request, req_data);

	QEventLoop loop;
    connect(reply, SIGNAL(finished()), &loop, SLOT(quit()));
	loop.exec();

	if (reply->error() == QNetworkReply::NoError) {
		QByteArray response = reply->readAll();
        QJsonDocument resp_doc = QJsonDocument::fromJson(response);
        if (resp_doc.isObject()) {
        	QJsonObject resp_obj = resp_doc.object();
        	uint32_t result = resp_obj.value(RESP_KEY_RESULT).toInt();
        	QString result_msg = resp_obj.value(RESP_KEY_RESULT_MSG).toString();
        	if (result == 0) {
	        	qInfo() << "[HTTP]Device Report success!";

	        	QJsonObject data_request_obj = resp_obj.value(RESP_KEY_DATA).toObject();
                if (!data_request_obj.empty()) {
	                uint32_t req_data_type = data_request_obj.value(RESP_KEY_REQUEST_TYPE).toInt();
	                uint32_t req_data_mach_id = data_request_obj.value(RESP_KEY_DEV_ID).toInt();
		        	QString req_data_from_date = data_request_obj.value(RESP_KEY_FROM_DATE).toString();
		        	QString req_data_to_date = data_request_obj.value(RESP_KEY_TO_DATE).toString();
		        	QString req_data_limit_size = data_request_obj.value(RESP_KEY_SIZE_LIMIT).toString();
                    if (req_data_limit_size.isNull())
		        		req_data_limit_size = "100000000";
		        	if (!req_data_from_date.isNull() && !req_data_to_date.isNull()) {
		        		QDateTime from, to;
		        		from = QDateTime::fromString(req_data_from_date, "yyyy-MM-dd hh:mm:ss");
		        		to = QDateTime::fromString(req_data_to_date, "yyyy-MM-dd hh:mm:ss");
		        		from = from.addSecs(-1);
		        		to = to.addSecs(1);
		        		if (req_data_type == RESP_REQUEST_LOG_TYPE) {
							if (FilterLogMessage(from, to)) {
						        QString program = "./send_log.sh";
				        		req_data_from_date = from.toString("yyyyMMdd.hhmmss");
				        		req_data_to_date = to.toString("yyyyMMdd.hhmmss");
						        QStringList arguments;
	                            arguments << QString("%1").arg(req_data_mach_id) << req_data_from_date << req_data_to_date << req_data_limit_size << m_server_address;
						        QProcess::startDetached(program, arguments);
	                            qInfo() << "[HTTP]Send Log File" << arguments;
							}
		        		}
		        		else if (req_data_type == RESP_REQUEST_SURVEILLANCE_TYPE) {
					        QString program = "./send_surveillance.sh";
				        	req_data_from_date = from.toString("yyyyMMdd.hhmmss");
				        	req_data_to_date = to.toString("yyyyMMdd.hhmmss");
					        QStringList arguments;
	                        arguments << QString("%1").arg(req_data_mach_id) << req_data_from_date << req_data_to_date << req_data_limit_size << m_server_address;
					        QProcess::startDetached(program, arguments);
	                        qInfo() << "[HTTP]Send Surveillance Files" << arguments;
		        		}
		        	}
	        	}
	        	QJsonObject setting_obj = resp_obj.value(RESP_KEY_SETTING_OBJ).toObject();
                if (!setting_obj.empty()) {
                	if (!setting_obj.value(RESP_KEY_AUTO_COUNT).isUndefined())
                		m_coordinator->set_auto_count(setting_obj.value(RESP_KEY_AUTO_COUNT).toBool());
                	if (!setting_obj.value(RESP_KEY_AUTO_STORE).isUndefined())
                		m_coordinator->set_auto_store(setting_obj.value(RESP_KEY_AUTO_STORE).toBool());
                	if (!setting_obj.value(RESP_KEY_USE_AMOUNT_LIMIT).isUndefined())
                        m_coordinator->set_use_amount_limit(setting_obj.value(RESP_KEY_USE_AMOUNT_LIMIT).toBool());
                	if (!setting_obj.value(RESP_KEY_ACCOUNT_FAILED_TRANS).isUndefined())
                		m_coordinator->set_account_failed_trans(setting_obj.value(RESP_KEY_ACCOUNT_FAILED_TRANS).toBool());
                }
        	}
	        else
	        	qInfo() << "[HTTP]Device Report failed!" << result << result_msg;
        }
		m_online = true;
        m_heartbreak_timer->setInterval(m_heartbreak_period);
	}
	else {
		qInfo() << "[HTTP]Failure" << reply->errorString();
		m_online = false;
        m_heartbreak_timer->setInterval(HeartBreak_Period_Abnormal);

        // check wwan connection, if disconnected, try to re-connect
        QString program = "./restart_wwan.sh";
        QStringList arguments;
        QProcess::startDetached(program, arguments);
	}
	delete reply;
}

HttpCloud::HttpCloud(QObject *parent)
{
	m_coordinator = qobject_cast<Coordinator *>(parent);

	m_worker = new HttpCloud_Worker(m_coordinator);
	m_worker->moveToThread(&m_worker_thread);

	connect(&m_worker_thread, &QThread::finished, m_worker, &QObject::deleteLater);
    connect(this, &HttpCloud::start, m_worker, &HttpCloud_Worker::start_work);
    connect(this, &HttpCloud::stop, m_worker, &HttpCloud_Worker::stop_work);

    m_worker_thread.setObjectName("HTTP Thread");
	m_worker_thread.start();
}

HttpCloud::~HttpCloud()
{
	m_worker_thread.quit();
	m_worker_thread.wait();
}

#include "qt-aes/qaesencryption.h"

QByteArray HttpCloud_Worker::s_aes_private_key;

QByteArray HttpCloud_Worker::aes_encrypt(QByteArray ba)
{
    QAESEncryption encryption(QAESEncryption::AES_256, QAESEncryption::ECB, QAESEncryption::PKCS7);
    return encryption.encode(ba, s_aes_private_key).toBase64();
}

QByteArray HttpCloud_Worker::aes_decrypt(QByteArray ba)
{
    QAESEncryption encryption(QAESEncryption::AES_256, QAESEncryption::ECB, QAESEncryption::PKCS7);
    QByteArray decodedText = encryption.decode(QByteArray::fromBase64(ba), s_aes_private_key);
    decodedText = encryption.RemovePadding(decodedText, QAESEncryption::PKCS7);

    return decodedText;
}

/*
Examples:

{
	"reportType":"TDSQ",
	"deviceNo":"M000T00100",
	"operatorID":"123456",
	"userName":"123456",
	"siteName":"测试站点",
	"tradeDate":"20240528",
	"tradeTime":"150748",
	"tradeNo":"2024052800000001",

	"depositType":"油款",
	"tradePiece":"23",
	"tradeAmount":"366.0",
	"transInfos":[
		{
			"tradeType":"01"
			"amount":300,
			"piece":11,
			"serialInfo":[
				{
					"country":"CNY",
					"serialNo":"U33W167986",
					"tfflag":"1",
					"unitvalue":"100"
				},
				{
					"country":"CNY",
					"serialNo":"RX98854163",
					"tfflag":"1",
					"unitvalue":"50"
				},
				{
					"country":"CNY",
					"serialNo":"YR74296668",
					"tfflag":"1",
					"unitvalue":"50"
				},
				{
					"country":"CNY",
					"serialNo":"PA65722009",
					"tfflag":"1",
					"unitvalue":"20"
				},
				{
					"country":"CNY",
					"serialNo":"HB19011023",
					"tfflag":"1",
					"unitvalue":"20"
				},
				{
					"country":"CNY",
					"serialNo":"DT87769274",
					"tfflag":"1",
					"unitvalue":"10"
				},
				{
					"country":"CNY",
					"serialNo":"CC81804178",
					"tfflag":"1","unitvalue":"10"
				},
				{
					"country":"CNY",
					"serialNo":"GU10456851",
					"tfflag":"1",
					"unitvalue":"10"
				},
				{
					"country":"CNY",
					"serialNo":"ZB23349907",
					"tfflag":"1",
					"unitvalue":"10"
				},
				{
					"country":"CNY",
					"serialNo":"YB77085744",
					"tfflag":"1",
					"unitvalue":"10"
				},
				{
					"country":"CNY",
					"serialNo":"AH54424437",
					"tfflag":"1",
					"unitvalue":"10"
				}
			]
		},
		{
			"tradeType":"02",
			"amount":66,
			"piece":12,
			"serialInfo":[
			]
		}
	]
}

{
	"reportType":"MSSQ",
	"deviceNo":"M000T00100",
	"deviceStatus":"0",
	"status":"2"

	"boxDeposit":0,
	"boxDepositPiece":0,
	"boxManual":0,
	"boxManualPiece":0,
	"boxStatus":"2",
}

*/
